#include <os/db/resultset_pg.hpp>
namespace iotplat {
    CResultSetPg::CResultSetPg() : m_rst(NULL) {

    }

    CResultSetPg::~CResultSetPg() {
        if (m_rst != NULL)
            PQclear(m_rst);
    }

    int CResultSetPg::size() const {
        if (m_rst != NULL)
            return PQntuples(m_rst);

        return 0;
    }

    bool CResultSetPg::next() {
        if (m_rst != NULL) {
            if (m_r == size())
                return false;

            ++m_r;
            if (m_r == size())
                return false;
            return true;
        }

        return false;
    }

    void CResultSetPg::reset() {
        m_r = -1;
    }

    template<typename T>
    inline T getValue(const PGresult *rs, int r, int c) {
        return *((T *) PQgetvalue(rs, r, c));
    }

    template<typename T>
    inline T getValue(const PGresult *rs, int r, const char *name) {
        return getValue<T>(rs, r, PQfnumber(rs, name));
    }

    bool CResultSetPg::asBool(int col) const {
        if (PQfformat(m_rst, col) != 0)
            return getValue<bool>(m_rst, m_r, col);
        else {
            const char *v = PQgetvalue(m_rst, m_r, col);
            return 't' == v[0] || 'T' == v[0];
        }
    }

    bool CResultSetPg::asBool(const char *col) const {
        return asBool(PQfnumber(m_rst, col));
    }

    int CResultSetPg::asInt(int col) const {
        if (PQfformat(m_rst, col) != 0)
            return getValue<int>(m_rst, m_r, col);
        else
            return atoi(PQgetvalue(m_rst, m_r, col));
    }

    int CResultSetPg::asInt(const char *col) const {
        return asInt(PQfnumber(m_rst, col));
    }

    uint CResultSetPg::asUint(int col) const {
        if (PQfformat(m_rst, col) != 0)
            return getValue<uint>(m_rst, m_r, col);
        else
            return atoi(PQgetvalue(m_rst, m_r, col));
    }

    uint CResultSetPg::asUint(const char *col) const {
        return asUint(PQfnumber(m_rst, col));
    }

    int64_t CResultSetPg::asInt64(int col) const {
        if (PQfformat(m_rst, col) != 0)
            return getValue<int64_t>(m_rst, m_r, col);
        else
            return atol(PQgetvalue(m_rst, m_r, col));
    }

    int64_t CResultSetPg::asInt64(const char *col) const {
        return asInt64(PQfnumber(m_rst, col));
    }

    double CResultSetPg::asDouble(int col) const {
        if (PQfformat(m_rst, col) != 0)
            return getValue<double>(m_rst, m_r, col);
        else
            return atof(PQgetvalue(m_rst, m_r, col));
    }

    double CResultSetPg::asDouble(const char *col) const {
        return asDouble(PQfnumber(m_rst, col));
    }

    std::string CResultSetPg::asString(int col) const {
        return PQgetvalue(m_rst, m_r, col);
    }

    std::string CResultSetPg::asString(const char *col) const {
        return PQgetvalue(m_rst, m_r, PQfnumber(m_rst, col));
    }

    bool CResultSetPg::isNull(int col) const {
        return PQgetisnull(m_rst, m_r, col);
    }

    bool CResultSetPg::isNull(const char *col) const {
        return PQgetisnull(m_rst, m_r, PQfnumber(m_rst, col));
    }

    int CResultSetPg::columnSize() const {
        if (m_rst != NULL) {
            return PQnfields(m_rst);
        }

        return 0;
    }

    std::string CResultSetPg::valueString(int col) const {
        if (m_rst != NULL) {
        }
        return "";
    }

    std::string CResultSetPg::valueString(const char *col) const {
        return valueString(PQfnumber(m_rst, col));
    }

    void CResultSetPg::free() {
        if (m_rst != NULL) {
            PQclear(m_rst);
            m_rst = NULL;
        }
    }
}
